package top.lixunda.demo.seata.good.rest;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.seata.core.context.RootContext;
import io.seata.core.exception.TransactionException;
import io.seata.spring.annotation.GlobalTransactional;
import io.seata.tm.api.GlobalTransaction;
import io.seata.tm.api.GlobalTransactionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import top.lixunda.demo.seata.common.controller.MessageObject;
import top.lixunda.demo.seata.common.entity.DbGood;
import top.lixunda.demo.seata.common.exception.AppException;
import top.lixunda.demo.seata.feign.GoodClient;
import top.lixunda.demo.seata.good.service.IDbGoodService;

import java.util.List;

/**
 * @author LiXunda
 * @version time:2019/10/25 13:01
 */
@RestController
@Slf4j
public class GoodController implements GoodClient {

    private final IDbGoodService goodService;

    @Autowired
    public GoodController(IDbGoodService goodService) {
        this.goodService = goodService;
    }

    /**
     * 根据商品号获取一个商品详细信息
     *
     * @param id 商品id
     * @return MessageObject
     */
    @Override
    public MessageObject<DbGood> getGoodById(int id) {
        DbGood good = goodService.getOne(new QueryWrapper<DbGood>().lambda().eq(DbGood::getGId, id), false);
        if (good == null) {
            throw AppException.message("商品不存在");
        }
        log.debug("获取商品成功 " + good.toString());
        return MessageObject.success(good);
    }

    /**
     * 查询所有商品信息
     *
     * @return DBGood列表
     */
    @Override
    public MessageObject<List<DbGood>> queryAll() {
        List<DbGood> goods = goodService.list();
        return MessageObject.success(goods);
    }

    /**
     * 自定义异常处理
     *
     * @param e AppException
     * @return MessageObject，这里其中的object为null，可以转换为任意类型
     */
    @ExceptionHandler(AppException.class)
    public MessageObject<Object> appException(AppException e) throws TransactionException {
        e.printStackTrace();
        //不行，不能回滚
        log.debug("xid : {}", RootContext.getXID());
        //不知道为什么必须使用 GlobalTransactionContext.reload(RootContext.getXID()) 才能进行回滚
        //不能使用 GlobalTransactionContext.getCurrentOrCreate()

        GlobalTransaction globalTransaction = GlobalTransactionContext.reload(RootContext.getXID());
        globalTransaction.rollback();
        return MessageObject.error("发生了异常");
    }

    /**
     * 减少商品库存
     *
     * @param goodId 商品唯一id
     * @param count  商品数量
     * @return MessageObject
     */
    @Override
    @GlobalTransactional
    public MessageObject<Boolean> reduceStock(int goodId, int count) {
        DbGood good = goodService.getOne(new QueryWrapper<DbGood>().lambda().eq(DbGood::getGId, goodId), false);
        if (good == null) {
            throw AppException.message("商品不存在");
        }
        if (good.getGStock() < count) {
            throw AppException.message("库存不足");
        }

        good.setGStock(good.getGStock() - count);
        boolean flag = goodService.updateById(good);
        if (!flag) {
            throw AppException.message("减少商品库存失败");
        }
        return MessageObject.success(true);
    }
}
